<?php

	class Db_ListBehavior extends Phpr_ControllerBehavior
	{
		public $list_model_class = null;
		public $list_name = null;
		public $list_items_per_page = 20;
		public $list_no_data_message = 'There are no items in this view';
		public $list_load_indicator = 'phproad/resources/images/form_load_50x50.gif';
		public $list_record_url = null;
		public $list_record_onclick = null;
		public $list_handle_row_click = true;
		public $list_render_as_tree = false;
		public $list_no_sorting = false;
		public $list_data_context = null;
		public $list_reuse_model = true;
		public $list_node_expanded_default = true;
		
		public $list_csv_import_url = '#';
		public $list_csv_cancel_url = '#';
		public $list_csv_template_url = '#';
		
		public $list_search_enabled = false;
		public $list_search_show_empty_query = true;
		public $list_search_prompt = null;
		public $list_search_fields = array();
		public $list_search_custom_func = null;

		public $list_no_interaction = false;
		public $list_no_js_declarations = false;
		public $list_no_form = false;
		public $list_no_setup_link = false;
		public $list_no_pagination = false;
		public $list_scrollable = false;
		
		public $list_custom_body_cells = null;
		public $list_custom_head_cells = null;
		public $list_cell_partial = false;
		public $list_custom_partial = null;
		public $list_cell_individual_partial = array();
		public $list_top_partial = null;
		public $list_control_panel = null;
		public $list_sidebar_panel = null;
		
		public $list_render_filters = false;

		public $list_columns = array();
		public $list_options = array();

		protected $_model_object = null;
		protected $_total_item_number = null;
		protected $_list_settings = null;
		protected $_list_columns = null;
		protected $_list_column_number = null;
		protected $_list_sorting_column = null;

		public function __construct($controller)
		{
			parent::__construct($controller);
			$this->hideAction('listPrepareData');
			$this->addEventHandler('onListColumnClick');
			$this->addEventHandler('onLoadListSetup');
			$this->addEventHandler('onApplyListSettings');

			$this->addEventHandler('onListPrevPage');
			$this->addEventHandler('onListNextPage');
			$this->addEventHandler('onListSetPage');
			$this->addEventHandler('onListToggleNode');
			$this->addEventHandler('onListReload');
			$this->addEventHandler('onListSearch');
			$this->addEventHandler('onListSearchCancel');
			
			$this->_controller->addCss('/phproad/modules/db/behaviors/db_listbehavior/resources/css/list.css?'.module_build('core'));
		}

		/**
		 *
		 * Public methods - you may call it from your views
		 *
		 */
		
		public function listRender($options = array(), $partial = null)
		{
			$this->_model_object = null;
			$this->_total_item_number = null;
			$this->_list_settings = null;
			$this->_list_columns = null;
			$this->_list_column_number = null;
			$this->_list_sorting_column = null;

			$this->applyOptions($options);

			$this->prepareRenderData();

			if (!$partial)
				$this->renderPartial('list_container');
			else
				$this->renderPartial($partial);
		}

		public function listCellClass($columnDefinition)
		{
			$result = $columnDefinition->type;
			$result .= $columnDefinition->index == $this->_list_column_number-1 ? ' last' : null;
			
			$sortingColumn = $this->_controller->listOverrideSortingColumn($this->evalSortingColumn());
			if ($sortingColumn->field == $columnDefinition->dbName)
			{
				$result .= ' current ';
				$result .= $sortingColumn->direction == 'asc' ? 'order_asc' : 'order_desc';
			}

			return $result;
		}

		public function listApplyOptions($options)
		{
			$this->applyOptions($options);
		}

		public function listGetName()
		{
			if ($this->_controller->list_name !== null)
				return $this->_controller->list_name;

			return get_class($this->_controller).'_'.Phpr::$router->action.'_list';
		}
		
		public function listGetFormId()
		{
			return 'listform'.$this->listGetName();
		}
		
		public function listGetPopupFormId()
		{
			return 'listform_popup'.$this->listGetName();
		}

		public function listGetContainerId()
		{
			return 'list'.$this->listGetName();
		}

		public function listGetElementId($element)
		{
			return $element.$this->listGetName();
		}
		
		public function listRenderPartial($view, $params=array(), $throwNotFound=true)
		{
			$model = $this->createModelObject();
			
			$this->renderControllerPartial($model->native_controller, $view, $params, false, $throwNotFound);
		}

		public function listEvalTotalItemNumber()
		{
			if ($this->_total_item_number !== null)
				return $this->_total_item_number;
				
			$model = $this->loadData();
			return $this->_total_item_number = $this->_controller->listGetTotalItemNumber($model);
		}

		public function listRenderTable()
		{
			$this->renderTable();
		}
		
		public function listRenderCsvImport()
		{
			$completed = false;
			
			if (post('postback'))
			{
				try
				{
					Phpr_Files::validateUploadedFile($_FILES['file']);
					$fileInfo = $_FILES['file'];

					$pathInfo = pathinfo($fileInfo['name']);
					if (!isset($pathInfo['extension']) || strtolower($pathInfo['extension']) != 'csv')
						throw new Phpr_ApplicationException('Imported file is not a CSV file.');

					$filePath = null;
					try
					{
						if (!is_writable(PATH_APP.'/temp/'))
							throw new Phpr_SystemException('There is no writing permissions for the directory: '.PATH_APP.'/temp');

						$filePath = PATH_APP.'/temp/'.uniqid('csv');
						if (!move_uploaded_file($fileInfo['tmp_name'], $filePath))
							throw new Phpr_SystemException('Unable to copy the uploaded file to '.$filePath);
							
						$modelClass = $this->_controller->list_model_class;
						$model_object = new $modelClass();
						if (!$model_object->isExtendedWith('Core_ModelCsv'))
							throw new Phpr_SystemException("The mode class {$modelClass} should be extended wit the Core_ModelCsv extension.");

						$row = 0;
						$handle = fopen($filePath, "r");
						$errors = array();
						$success = 0;
						
						$delimeter = Phpr_Files::determineCsvDelimeter($filePath);
						if (!$delimeter)
							throw new Phpr_SystemException('Unable to detect the file type');
							
						$completed = true;

						while (($data = fgetcsv($handle, 1000, $delimeter)) !== FALSE) 
						{
							$row++;
							if ($row == 1 || !Phpr_Files::convertCsvEncoding($data))
								continue;

							$model_object = new $modelClass();
							try
							{
								$model_object->csv_import_record($data);
								$success++;
							} catch (Exception $import_exception)
							{
								$errors[$row] = $import_exception->getMessage();
							}
						}
						$this->viewData['errors'] = $errors;
						$this->viewData['success'] = $success;

						@unlink($filePath);
					}
					catch (Exception $ex)
					{
						if (strlen($filePath) && @file_exists($filePath))
							@unlink($filePath);

						throw $ex;
					}
				}
				catch (Exception $ex)
				{
					$this->viewData['form_error'] = $ex->getMessage();
				}
			}

			$this->viewData['completed'] = $completed;
			$this->renderPartial('list_import_csv');
		}

		public function listExportCsv($filename, $options = array(), $filterCallback = null, $noColumnInfoInit = false)
		{
			Backend::$events->fireEvent('core:onBeforeListExport', $this->_controller);

			$this->applyOptions($options);

			$data_model = $this->loadData();
			$column_defintions = $data_model->get_column_definitions($this->_controller->list_data_context);
			$sortingColumn = $this->_controller->listOverrideSortingColumn($this->evalSortingColumn());
			$sortingField = $column_defintions[$sortingColumn->field]->getSortingColumnName();

			$list_sort_column = $sortingField.' '.$sortingColumn->direction;
			$data_model->reset_order();
			$data_model->order($list_sort_column);

			$list_columns = $listColumns = $this->evalListColumns();

			$data_model->applyCalculatedColumns();
			$query = $data_model->build_sql();
			
			header("Expires: 0");
			header("Content-Type: Content-type: text/csv");
			header("Content-Description: File Transfer");
			header("Cache-control: private");
			header('Cache-Control: no-store, no-cache, must-revalidate');
			header('Cache-Control: pre-check=0, post-check=0, max-age=0');
			header("Content-disposition: attachment; filename=$filename");

			$this->_controller->suppressView();

			$header = array();
			foreach ($list_columns as $column)
				$header[] = strlen($column->listTitle) ? $column->listTitle : $column->displayName;
				
			$iwork = array_key_exists('iwork', $options) ? $options['iwork'] : false;
			$separator = $iwork ? ',' : ';';

			Phpr_Files::outputCsvRow($header, $separator);

			$list_data = Db_DbHelper::queryArray($query);
			foreach ($list_data as $row_data)
			{
				$row = $data_model;
				$row->fill($row_data);
				
				if ($filterCallback)
				{
					if (!call_user_func($filterCallback, $row))
						continue;
				}
				
				$row_data = array();
				foreach ($list_columns as $index=>$column)
					$row_data[] = $row->displayField($column->dbName, 'list');

				Phpr_Files::outputCsvRow($row_data, $separator);
			}
		}

		public function listCancelSearch()
		{
			Phpr::$session->set($this->listGetName().'_search', '');
		}
		
		public function listResetCache()
		{
			$this->_model_object = null;
			$this->_total_item_number = null;
			$this->_list_settings = null;
			$this->_list_columns = null;
			$this->_list_column_number = null;
			$this->_list_sorting_column = null;
		}
		
		/**
		 *
		 * Common methods - you may want to override them in the controller
		 *
		 */

		/**
		 * Returns a configured model object. 
		 * @return Db_ActiveRecord
		 */
		public function listPrepareData()
		{
			$obj = $this->createModelObject();
			return $obj;
		}
		
		public function listExtendModelObject($model)
		{
			return $model;
		}

		/**
		 * Returns a total number of items, not limited by a current page.
		 * @return int
		 */
		public function listGetTotalItemNumber($model)
		{
			return $model->requestRowCount();
		}

		public function listFormatRecordUrl($model)
		{
			$record_url = $this->_controller->list_record_url;
			
			if (!strlen($record_url))
			{
				if (!strlen($this->_controller->list_record_onclick))
					return null;
					
				return "#";
			}

			if (strpos($record_url, '%s'))
				return sprintf($record_url, $model->id);
			else
				return $record_url.$model->id;
		}

		public function listFormatRecordOnClick($model)
		{
			$onclick = $this->_controller->list_record_onclick;
			
			if (!strlen($onclick))
				return null;

			if (strpos($onclick, '%s'))
				return 'onclick="'.sprintf($onclick, $model->id).'"';
			else
				return 'onclick="'.$onclick.'"';
		}
		
		public function listFormatCellOnClick($model)
		{
			$onclick = $this->_controller->list_record_onclick;
			
			if (!strlen($onclick))
				return null;

			if (strpos($onclick, '%s'))
				return sprintf($onclick, $model->id);

			return $onclick;
		}

		public function listNodeIsExpanded($node)
		{
			return Db_UserParameters::get($this->listGetName().'_treenodestatus_'.$node->id, null, $this->_controller->list_node_expanded_default);
		}
		
		public function listResetPage()
		{
			Phpr::$session->set($this->listGetName().'_page', 0);
		}

		public function listGetRowClass($model)
		{
			return null;
		}
		
		public function listBeforeRenderRecord($model)
		{
		}

		public function listOverrideSortingColumn($sorting_column)
		{
			return $sorting_column;
		}

		/**
		 *
		 * Event handlers
		 *
		 */
		
		public function onListColumnClick()
		{
			$column = post('columnName');
			if (strlen($column))
			{
				$sortingColumn = $this->_controller->listOverrideSortingColumn($this->evalSortingColumn());
				if ($sortingColumn->field == $column)
					$sortingColumn->direction = $sortingColumn->direction == 'asc' ? 'desc' : 'asc';
				else
				{
					$sortingColumn->field = $column;
					$sortingColumn->direction = 'asc';
				}
				
				$sortingColumn = $this->_controller->listOverrideSortingColumn($sortingColumn);
				
				$this->saveSortingColumn($sortingColumn);
				$this->renderTable();
			}
		}
		
		public function onListNextPage()
		{
			try
			{
				$page = $this->evalPageNumber() + 1;
				$this->setPageNumber($page);
			
				$this->renderTable();
			}
			catch (Exception $ex)
			{
				Phpr::$response->ajaxReportException($ex, true, true);
			}
		}
		
		public function onListPrevPage()
		{
			try
			{
				$page = $this->evalPageNumber() - 1;
				$this->setPageNumber($page);

				$this->renderTable();
			}
			catch (Exception $ex)
			{
				Phpr::$response->ajaxReportException($ex, true, true);
			}
		}
		
		public function onListSetPage()
		{
			try
			{
				$this->setPageNumber(post('pageIndex'));

				$this->renderTable();
			}
			catch (Exception $ex)
			{
				Phpr::$response->ajaxReportException($ex, true, true);
			}
		}

		public function onLoadListSetup()
		{
			$listSettings = $this->loadListSettings();
			$this->viewData['columns'] = $this->evalListColumns(false);
			$this->viewData['visibleColumns'] = $listSettings['visible_list'];
			$this->viewData['invisibleColumns'] = $listSettings['invisible_list'];
			$this->viewData['list_load_indicator'] = $this->_controller->list_load_indicator;
			$this->viewData['records_per_page'] = $listSettings['records_per_page'];

			$this->renderPartial('list_settings_form');
		}
		
		public function onApplyListSettings()
		{
			$model = $this->createModelObject();
			$listSettings = $this->loadListSettings();

			/*
			 * Apply visible columns
			 */
			$visibleColumns = array_keys(post('list_visible_colums', array()));
			$listSettings['visible_list'] = $visibleColumns;
			
			/*
			 * Apply invisible columns
			 */
			$invisibleColumns = array();
			$definitions = $model->get_column_definitions($this->_controller->list_data_context);
			foreach ($definitions as $dnName=>$definition)
			{
				if (!in_array($dnName, $visibleColumns))
					$invisibleColumns[] = $dnName;
			}
			$listSettings['invisible_list'] = $invisibleColumns;

			/*
			 * Apply column order columns
			 */
			$listSettings['column_order'] = post('ordered_list', array());

			/*
			 * Apply records per page
			 */
			$listSettings['records_per_page'] = post('records_per_page', $this->_controller->list_items_per_page);

			$this->saveListSettings($listSettings);
			$this->renderTable();
		}

		public function onListToggleNode()
		{
			Db_UserParameters::set($this->listGetName().'_treenodestatus_'.post('nodeId'), post('status') ? 0 : 1);
			$this->renderTable();
		}
		
		public function onListReload()
		{
			$this->renderTable();
		}
		
		public function onListSearch()
		{
			$search_string = post('search_string');
			Phpr::$session->set($this->listGetName().'_search', $search_string);

			$this->renderTable();
		}
		
		public function onListSearchCancel()
		{
			Phpr::$session->set($this->listGetName().'_search', '');
			$this->renderTable();
		}

		/**
		 *
		 * Protected methods - used by the behavior
		 *
		 */

		/**
		 * Returns a list of list columns in correct order
		 */
		protected function evalListColumns($onlyVisible = true)
		{
			if ($this->_list_columns !== null && $onlyVisible)
				return $this->_list_columns;

			$model = $this->createModelObject();
			$listSettings = $this->loadListSettings();

			$definitions = $model->get_column_definitions($this->_controller->list_data_context);
			if (!count($definitions))
				throw new Phpr_ApplicationException('Error rendering list: model columns are not defined.');

			$visibleFound = false;
			foreach ($definitions as $definition)
			{
				if ($definition->visible)
				{
					$visibleFound = true;
					break;
				}
			}
			if (!$visibleFound)
				throw new Phpr_ApplicationException('Error rendering list: there are no visible columns defined in the model.');

			if (count($this->_controller->list_columns))
				$orderedList = $this->_controller->list_columns;
			else
			{
				$columnList = array();

				/*
				 * Add visible columns
				 */
				foreach ($listSettings['visible_list'] as $columnName)
				{
					if (array_key_exists($columnName, $definitions) && $definitions[$columnName]->visible)
						$columnList[] = $columnName;
				}

				/*
				 * Add remaining columns if they are not invisible
				 */
				foreach ($definitions as $columnName=>$definition)
				{
					if (!in_array($columnName, $columnList) && (!in_array($columnName, $listSettings['invisible_list']) || !$onlyVisible) && $definition->visible
					&& (($onlyVisible && $definitions[$columnName]->defaultVisible) || !$onlyVisible))
						$columnList[] = $columnName ;
				}
			
				/*
				 * Apply column order
				 */
				$orderedList = array();
				if (!count($listSettings['column_order']))
					$listSettings['column_order'] = array_keys($definitions);
				
				foreach ($listSettings['column_order'] as $columnName)
				{
					if (in_array($columnName, $columnList))
						$orderedList[] = $columnName;
				}
			
				foreach ($columnList as $columnName)
				{
					if (!in_array($columnName, $orderedList))
						$orderedList[] = $columnName;
				}
			}

			$result = array();
			foreach ($orderedList as $index=>$columnName)
			{
				$definitionObj = $definitions[$columnName];
				$definitionObj->index = $index;
				$result[] = $definitionObj;
			}
			
			$this->_list_column_number = count($result);
			if ($onlyVisible)
				$this->_list_columns = $result;
				
			return $result;
		}

		protected function evalSortingColumn()
		{
			if (strlen($this->_controller->list_sorting_column))
			{
				$column = $this->_controller->list_sorting_column;
				return (object)(array('field'=>$column, 'direction'=>'asc'));
			}
			
			if ($this->_list_sorting_column !== null)
				return $this->_list_sorting_column;
				
			$listColumns = $this->evalListColumns();
			$model = $this->createModelObject();
			$listSettings = $this->loadListSettings();
			$definitions = $model->get_column_definitions();

			if (strlen($listSettings['sorting']->field) && array_key_exists($listSettings['sorting']->field, $definitions) )
				return $listSettings['sorting'];

			foreach ($definitions as $columnName=>$definition)
			{
				if ($definition->defaultOrder !== null)
					return (object)(array('field'=>$columnName, 'direction'=>$definition->defaultOrder));
			}

			if (!count($listColumns))
				return null;

			$columnNames = array_keys($listColumns);
			$firstColumn = $columnNames[0];

			$this->_list_sorting_column = (object)(array('field'=>$listColumns[$firstColumn]->dbName, 'direction'=>'asc'));
			return $this->_list_sorting_column;
		}
		
		protected function evalPageNumber()
		{
			return Phpr::$session->get($this->listGetName().'_page', 0);
		}
		
		protected function setPageNumber($page)
		{
			Phpr::$session->set($this->listGetName().'_page', $page);
		}
		
		protected function saveSortingColumn($sortingObj)
		{
			$listSettings = $this->loadListSettings();
			$listSettings['sorting'] = $sortingObj;
			$this->saveListSettings($listSettings);
		}

		protected function prepareRenderData($no_pagination = false, $noColumnInfoInit = false)
		{
			$form_context = $this->_controller->list_data_context;
			
			$this->viewData['list_columns'] = $listColumns = $this->evalListColumns();
			$this->viewData['list_sorting_column'] = $sortingColumn = $this->_controller->listOverrideSortingColumn($this->evalSortingColumn());
			$this->viewData['list_column_definitions'] = $this->createModelObject()->get_column_definitions();

			$model = $this->loadData();
			$column_defintions = $model->get_column_definitions($form_context);
			$totalRowCount = $this->listEvalTotalItemNumber();

			if (!$no_pagination && !$this->_controller->list_render_as_tree && !$this->_controller->list_no_interaction && !$this->_controller->list_no_pagination)
			{
				$listSettings = $this->loadListSettings();
				
				$pagination = new Phpr_Pagination($listSettings['records_per_page']);
				$pagination->setRowCount($totalRowCount);

				$pagination->setCurrentPageIndex($this->evalPageNumber());
				$pagination->limitActiveRecord($model);

				$this->viewData['list_pagination'] = $pagination;
			}

			$sortingField = $column_defintions[$sortingColumn->field]->getSortingColumnName();

			$list_sort_column = $sortingField.' '.$sortingColumn->direction;
			$model->order($list_sort_column);

			$this->viewData['list_model_class'] = get_class($model);
			$this->viewData['list_total_row_count'] = $totalRowCount;

			if ($noColumnInfoInit)
			{
				global $activerecord_no_columns_info;
				$activerecord_no_columns_info = true;
			}
			
			if (!$this->_controller->list_render_as_tree)
			{
				if (!$this->_controller->list_reuse_model)
					$this->viewData['list_data'] = $model->find_all(null, array(), $form_context);
				else
				{
					$model->applyCalculatedColumns();
					$query = $model->build_sql();
					$this->viewData['list_data'] = Db_DbHelper::queryArray($query);

					$this->viewData['reusable_model'] = $model;
				}
			} else
			{
				$this->_controller->list_reuse_model = false;
 				$this->viewData['list_data'] = $model->list_root_children($list_sort_column);
			}
			
			if ($noColumnInfoInit)
				$activerecord_no_columns_info = false;

			$this->viewData['list_no_data_message'] = $this->_controller->list_no_data_message;
			$this->viewData['list_sort_column'] = $list_sort_column;

			$this->viewData['list_column_count'] = count($listColumns);
			$this->viewData['list_load_indicator'] = $this->_controller->list_load_indicator;
			$this->viewData['list_tree_level'] = 0;
			$this->viewData['list_search_string'] = Phpr::$session->get($this->listGetName().'_search');
		}

		protected function renderTable()
		{
			$this->prepareRenderData();

			if (!$this->_controller->list_custom_partial)
				$this->renderPartial('list');
			else
				$this->renderPartial($this->_controller->list_custom_partial);
		}
		
		protected function loadListSettings()
		{
			if ($this->_list_settings === null)
			{
				$this->_list_settings = Db_UserParameters::get($this->listGetName().'_settings');

				if (!is_array($this->_list_settings))
					$this->_list_settings = array();
					
				if (!array_key_exists('visible_list', $this->_list_settings))
					$this->_list_settings['visible_list'] = array();
					
				if (!array_key_exists('invisible_list', $this->_list_settings))
					$this->_list_settings['invisible_list'] = array();
					
				if (!array_key_exists('column_order', $this->_list_settings))
					$this->_list_settings['column_order'] = array();
					
				if (!array_key_exists('sorting', $this->_list_settings))
					$this->_list_settings['sorting'] = (object)array('field'=>null, 'direction'=>null);
					
				if (!array_key_exists('records_per_page', $this->_list_settings))
					$this->_list_settings['records_per_page'] = $this->_controller->list_items_per_page;
			}
			
			return $this->_list_settings;
		}
		
		protected function saveListSettings($settings)
		{
			$this->_list_settings = $settings;
			Db_UserParameters::set($this->listGetName().'_settings', $settings);
		}

		protected function createModelObject()
		{
			if ($this->_model_object !== null)
				return $this->_model_object;

			if (!strlen($this->_controller->list_model_class))
				throw new Phpr_SystemException('Data model class is not specified for List Behavior. Use the list_model_class public field to set it.');
				
			$modelClass = $this->_controller->list_model_class;
			$result = $this->_model_object = new $modelClass();
			
			$result = $this->_controller->listExtendModelObject($result);
			
			return $result;
		}

		protected function applyOptions($options)
		{
			$this->_controller->list_options = $options;
			foreach ($options as $key=>$value)
				$this->_controller->$key = $value;
		}

		protected function loadData()
		{
			$model = null;

			if (strlen($this->_controller->list_custom_prepare_func))
			{
				$func = $this->_controller->list_custom_prepare_func;
				$model = $this->_controller->$func($this->createModelObject(), $this->_controller->list_options);
			} else
				$model = $this->_controller->listPrepareData();
			
			/*
			 * Apply search
			 */
			
			$search_string = Phpr::$session->get($this->listGetName().'_search');
			if ($this->_controller->list_search_enabled)
			{
				if (!$this->_controller->list_search_fields)
					throw new Phpr_ApplicationException('List search is enabled, but search fields are not specified in the list settings. Please use $list_search_fields public controller field to define an array of fields to search in.');
				
				if (!strlen($search_string) && !$this->_controller->list_search_show_empty_query)
				{
					$firstField = $this->_controller->list_search_fields[0];
					$model->where($firstField.' <> '.$firstField);
				} else
					if (strlen($search_string))
					{
						$this->_controller->list_render_as_tree = false;
						
						if (strlen($this->_controller->list_search_custom_func))
						{
							$func = $this->_controller->list_search_custom_func;
							$this->_controller->$func($model, $search_string);
						} else
						{
							$words = explode(' ', $search_string);
							$word_queries = array();
							foreach ($words as $word)
							{
								if (!strlen($word))
									continue;

								$word = trim(mb_strtolower($word));
								$word_queries[] = '%1$s like \'%2$s'.mysql_real_escape_string($word).'%2$s\'';
							}

							$field_queries = array();
							foreach ($this->_controller->list_search_fields as $field)
							{
								$field = str_replace('@', $model->table_name.'.', $field);

								$field_queries[] = '('.sprintf(implode(' and ', $word_queries), $field, '%').')';
							}

							$query = '('.implode(' or ', $field_queries).')';
							$model->where($query);
						}
					}
			}
			
			return $model;
		}
	}

?>